package com.cloud.wms.ui.inside.presenter;

import android.text.TextUtils;

import com.annimon.stream.Stream;
import com.cloud.core.base.BaseRxPresenter;
import com.cloud.core.http.error.ApiException;
import com.cloud.core.utils.MessageCreator;
import com.cloud.wms.R;
import com.cloud.wms.app.FineExApplication;
import com.cloud.wms.entity.ContainerEntity;
import com.cloud.wms.entity.Page;
import com.cloud.wms.http.Params;
import com.cloud.wms.http.observer.CheckNullFunc;
import com.cloud.wms.http.observer.LoadingObserver;
import com.cloud.wms.http.observer.ResponseWrapper;
import com.cloud.wms.tools.PageHelper;
import com.cloud.wms.tools.RxUtils;
import com.cloud.wms.tools.TaskHelper;
import com.cloud.wms.ui.inside.contract.ReplenishDownContract;
import com.cloud.wms.ui.inside.entity.ReplenishBindEntity;
import com.cloud.wms.ui.inside.entity.ReplenishCommodityEntity;
import com.cloud.wms.ui.inside.entity.ReplenishOrderEntity;
import com.cloud.wms.ui.inside.entity.ReplenishBatchEntity;
import com.cloud.wms.ui.inside.entity.ReplenishStateBean;
import com.cloud.wms.ui.main.entity.BatchEntity;
import com.cloud.wms.ui.main.entity.RemoteEntity;
import com.cloud.wms.ui.main.entity.TaskEntity;
import com.cloud.wms.ui.main.entity.UserEntity;

import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.concurrent.TimeUnit;

import javax.inject.Inject;

import io.reactivex.Observable;
import io.reactivex.ObservableSource;
import io.reactivex.functions.Function;

/**
 * Created by FC on 2021/3/12.
 * Desc：补货下架
 */
public class ReplenishDownPresenter extends BaseRxPresenter<ReplenishDownContract.View> implements ReplenishDownContract.Presenter {

    public static final int BIND_CONTAINER = 0x101;

    public static final int REPLENISH_COMMODITY = 0x102;

    public static final int CHECK_DOWN_POS = 0x103;

    public static final int GO_REPLENISH_SHELF = 0x104;

    public static final int REPLENISH_DOWN_COMPLETE = 0x107;

    public static final int REPLENISH_DETAIL = 0x105;

    public static final int CHECK_BIND_CONTAINER = 0x106;

    public static final int TASK = 0x108;

    public static final int REPLENISH_DOWN_FINISH = 0x109;

    public static final int REPLENISH_UP_FINISH = 0x110;


    @Inject
    public ReplenishDownPresenter() {

    }

    @Override
    public void loadReplenishOrder(String replenishCode, int page) {
        Params params = Params.newInstance(Params.Type.MEMBER);
        if (!TextUtils.isEmpty(replenishCode)) {
            params.put("ReplenishCode", replenishCode);
        }
        params.put("Sorting", "createDate");
        params.put("SkipCount", PageHelper.skipCount(page));
        params.put("MaxResultCount", PageHelper.PAGE_SIZE);
        FineExApplication
                .component()
                .http()
                .loadReplenishOrderList(params)
                .map(new ResponseWrapper<>())
                .compose(mView.toLifecycle())
                .compose(RxUtils.threadSwitch())
                .subscribe(new LoadingObserver<ArrayList<ReplenishOrderEntity>>(mView.provideContext()) {
                    @Override
                    public void onSuccess(ArrayList<ReplenishOrderEntity> info) {
                        if (page == 0) {
                            mView.onSuccess(MessageCreator.createMessage(info, PageHelper.LIST_NEW_DATA));
                        } else {
                            mView.onSuccess(MessageCreator.createMessage(info, PageHelper.LIST_NEXT_DATA));
                        }
                    }

                    @Override
                    public void onError(String msg) {
                        mView.error(msg);
                    }
                });
    }

    @Override
    public void receiveTask(long billId, String taskCode) {
        FineExApplication
                .component()
                .http()
                .orderTaskList(billId + "")
                .map(new ResponseWrapper<>())
                .map(RemoteEntity::getItems)
                .flatMap((Function<ArrayList<TaskEntity>, ObservableSource<TaskEntity>>) Observable::fromIterable)
                .filter(taskEntity -> taskEntity.getTaskCode().equalsIgnoreCase(taskCode))
                .toList()
                .toObservable()
                .flatMap((Function<List<TaskEntity>, ObservableSource<TaskEntity>>) taskEntities -> {
                    if (taskEntities == null || taskEntities.isEmpty()) {
                        return Observable.error(new ApiException("暂无可领用任务"));
                    }
                    TaskEntity taskEntity = taskEntities.get(0);
                    Params paramsTask = new Params();
                    paramsTask.put("TaskID", taskEntity.getTaskID());
                    UserEntity userInfo = FineExApplication.component().loginCache().getUserInfo();
                    paramsTask.put("JobStationID", userInfo.getJobStationID());
                    paramsTask.put("ProductCategory", userInfo.getProductCategory());
                    paramsTask.put("ExecutorID", userInfo.getUserID());

                    Params params = new Params();
                    params.put("BillID", billId);

                    return TaskHelper.receiveTask(paramsTask)
                            .map(aVoid -> {
                                taskEntity.setWorkID(aVoid);
                                taskEntity.setMainBillCode(taskEntity.getBillCode());
                                taskEntity.setMainBillID(taskEntity.getBillID());
                                return taskEntity;
                            })
                            .flatMap((Function<TaskEntity, ObservableSource<TaskEntity>>) task -> FineExApplication
                                    .component()
                                    .http()
                                    .loadReplenishOrderStatus(params)
                                    .map(new ResponseWrapper<>())
                                    .map(aVoid -> task));
                })
                .flatMap((Function<TaskEntity, ObservableSource<TaskEntity>>) taskEntity -> {
                    Params params = new Params();
                    params.put("workId", taskEntity.getWorkID());
                    UserEntity userInfo = FineExApplication.component().loginCache().getUserInfo();
                    params.put("executerId", userInfo.getUserID());
                    return TaskHelper.executeTask(params)
                            .map(aVoid -> taskEntity);
                })
                .compose(mView.toLifecycle())
                .compose(RxUtils.threadSwitch())
                .subscribe(new LoadingObserver<TaskEntity>(mView.provideContext()) {
                    @Override
                    public void onSuccess(TaskEntity info) {
                        mView.onSuccess(MessageCreator.createMessage(info, TASK));
                    }

                    @Override
                    public void onError(String msg) {
                        mView.error(msg);
                    }
                });
    }

    @Override
    public void checkBindContainer(long replenishId) {
        Params params = new Params();
        params.put("BillID", replenishId);

        FineExApplication
                .component()
                .http()
                .replenishCheckBind(params)
                .map(new ResponseWrapper<>())
                .map(new CheckNullFunc<ReplenishBindEntity>())
                .compose(mView.toLifecycle())
                .compose(RxUtils.threadSwitch())
                .subscribe(new LoadingObserver<ReplenishBindEntity>(mView.provideContext()) {
                    @Override
                    public void onSuccess(ReplenishBindEntity info) {
                        mView.showContent();
                        mView.onSuccess(MessageCreator.createMessage(info, CHECK_BIND_CONTAINER));
                    }

                    @Override
                    public void onError(String msg) {
                        mView.error(msg);
                        mView.showError();
                    }
                });
    }

    @Override
    public void bindContainer(long replenishId, String containerCode) {
        Params params = Params.newInstance(Params.Type.WAREHOUSE);
        params.put("BoxCode", containerCode);
        FineExApplication
                .component()
                .http()
                .checkContainerUseState(params)
                .map(new ResponseWrapper<>())
                .flatMap((Function<ContainerEntity, ObservableSource<ContainerEntity>>) containerEntity -> {
                    ArrayList<HashMap<String, Object>> list = new ArrayList<>();
                    HashMap<String, Object> map = new HashMap<>();
                    map.put("containerID", containerEntity.getContainerID());
                    map.put("orderID", replenishId);
                    list.add(map);
                    Params paramsBind = Params.newInstance(Params.Type.WAREHOUSE);
                    paramsBind.put("orderType", 5);
                    paramsBind.put("lstBox", list);
                    paramsBind.put("userID", FineExApplication.component().loginCache().getUserInfo().getUserID());
                    return FineExApplication
                            .component()
                            .http()
                            .replenishBindContainer(paramsBind)
                            .map(new ResponseWrapper<>())
                            .flatMap((Function<Boolean, ObservableSource<ContainerEntity>>) aBoolean -> {
                                if (!aBoolean)
                                    return Observable.error(new ApiException("绑定失败，请检查数据！"));
                                return Observable.just(containerEntity);
                            });
                })
                .map(containerEntity -> {
                    ReplenishBindEntity entity = new ReplenishBindEntity();
                    entity.setBillID(replenishId);
                    entity.setContainerCode(containerEntity.getContainerCode());
                    entity.setContainerID(containerEntity.getContainerID());
                    return entity;
                })
                .compose(mView.toLifecycle())
                .compose(RxUtils.threadSwitch())
                .subscribe(new LoadingObserver<ReplenishBindEntity>(mView.provideContext()) {
                    @Override
                    public void onSuccess(ReplenishBindEntity info) {
                        mView.onSuccess(MessageCreator.createMessage(info, BIND_CONTAINER));
                    }

                    @Override
                    public void onError(String msg) {
                        mView.error(msg);
                    }
                });
    }

    @Override
    public void loadReplenishCommodity(long replenishId) {
        Params params = Params.newInstance(Params.Type.WAREHOUSE);
        params.put("BillID", replenishId);
        params.put("QueryType", 1);
        FineExApplication.component().http()
                .loadReplenishDownCommodity(params)
                .map(new ResponseWrapper<>())
                .map(commodityEntities -> (ArrayList<ReplenishCommodityEntity>) Stream.of(commodityEntities)
                        .sortBy(ReplenishCommodityEntity::getFirstRecommendPosCode)
                        .toList())
                .flatMap((Function<ArrayList<ReplenishCommodityEntity>, ObservableSource<ReplenishCommodityEntity>>) Observable::fromIterable)
                .filter(commodityEntity -> !commodityEntity.isDownStatus())
                .toList()
                .toObservable()
                .compose(mView.toLifecycle())
                .compose(RxUtils.threadSwitch())
                .subscribe(new LoadingObserver<List<ReplenishCommodityEntity>>(mView.provideContext()) {
                    @Override
                    public void onSuccess(List<ReplenishCommodityEntity> info) {
                        if (info == null || info.isEmpty()) {
                            mView.onSuccess(MessageCreator.createMessage(info, REPLENISH_DOWN_COMPLETE));
                            return;
                        }
                        mView.onSuccess(MessageCreator.createMessage(info.get(0), REPLENISH_COMMODITY));
                    }

                    @Override
                    public void onError(String msg) {
                        mView.error(msg);
                    }
                });
    }

    @Override
    public void loadReplenishCommodity(long replenishId, boolean isComplete) {
        Params params = Params.newInstance(Params.Type.WAREHOUSE);
        params.put("BillID", replenishId);
        params.put("QueryType", 1);

        FineExApplication.component().http()
                .loadReplenishDownCommodity(params)
                .map(new ResponseWrapper<>())
                .map(commodityEntities -> (ArrayList<ReplenishCommodityEntity>) Stream.of(commodityEntities)
                        .sortBy(commodityEntity -> commodityEntity.getFirstRecommendPosCode())
                        .toList())
                .flatMap((Function<ArrayList<ReplenishCommodityEntity>, ObservableSource<ReplenishCommodityEntity>>) Observable::fromIterable)
                .filter(commodityEntity -> {
                    if (isComplete) {
                        return commodityEntity.isDownStatus();
                    } else {
                        return !commodityEntity.isDownStatus();
                    }
                })
                .toList()
                .toObservable()
                .compose(mView.toLifecycle())
                .compose(RxUtils.threadSwitch())
                .subscribe(new LoadingObserver<List<ReplenishCommodityEntity>>(mView.provideContext()) {
                    @Override
                    public void onSuccess(List<ReplenishCommodityEntity> info) {
                        if (info == null || info.isEmpty()) {
                            mView.showEmpty();
                        } else {
                            mView.onSuccess(MessageCreator.createMessage(info, REPLENISH_DETAIL));
                            mView.showContent();
                        }
                    }

                    @Override
                    public void onError(String msg) {
                        mView.error(msg);
                    }
                });
    }

    @Override
    public void checkDownPosCode(long billId, String posCode, long commodityId, int stockType) {
        Params params = Params.newInstance(Params.Type.MEMBER);
        params.put("BillID", billId);
        params.put("StockType", stockType);
        params.put("PosCode", posCode);
        FineExApplication.component().http()
                .checkReplenishDownPosCode(commodityId, params)
                .map(new ResponseWrapper<>())
                .compose(mView.toLifecycle())
                .compose(RxUtils.threadSwitch())
                .subscribe(new LoadingObserver<ArrayList<ReplenishBatchEntity>>(mView.provideContext()) {
                    @Override
                    public void onSuccess(ArrayList<ReplenishBatchEntity> info) {
                        mView.onSuccess(MessageCreator.createMessage(info, CHECK_DOWN_POS));
                    }

                    @Override
                    public void onError(String msg) {
                        mView.error(msg);
                    }
                });
    }

    @Override
    public void confirmReplenishDown(TaskEntity taskEntity,
                                     ReplenishBindEntity bindEntity,
                                     ReplenishCommodityEntity commodityEntity,
                                     ArrayList<BatchEntity> posBatchEntity,
                                     int amount,
                                     boolean isDownComplete,
                                     boolean isGoShelf) {
        Params params = Params.newInstance(Params.Type.MEMBER);
        params.put("billID", taskEntity.getBillID());
        params.put("replenishStatus", isDownComplete);
        if (bindEntity != null && bindEntity.getContainerID() > 0)
            params.put("containerID", bindEntity.getContainerID());
        params.put("workID", taskEntity.getWorkID());
        params.put("productCategory", taskEntity.getProductCategory());
        params.put("jobStationID", taskEntity.getJobStationID());


        ArrayList<HashMap<String, Object>> maps = new ArrayList<>();
        for (int i = 0; i < posBatchEntity.size(); i++) {
            HashMap<String, Object> map = new HashMap<>();
            map.put("stockType", commodityEntity.getStockType());
            map.put("posCode", commodityEntity.getPosCode());
            map.put("commodityID", commodityEntity.getCommodityId());
            if (amount >= posBatchEntity.get(i).getAmount()) {
                map.put("amount", posBatchEntity.get(i).getAmount());
                amount = amount - posBatchEntity.get(i).getAmount();
            } else {
                map.put("amount", amount);
                amount = 0;
            }
            map.put("productBatchID", posBatchEntity.get(i).getProductBatchID());

            maps.add(map);
            if (amount <= 0) {
                break;
            }
        }
        params.put("commoditylst", maps);

        FineExApplication.component().http()
                .confirmReplenishDown(params)
                .map(new ResponseWrapper<>())
                .compose(mView.toLifecycle())
                .compose(RxUtils.threadSwitch())
                .subscribe(new LoadingObserver<Object>(mView.provideContext()) {
                    @Override
                    public void onSuccess(Object info) {
                        mView.success("商品下架成功!");
                        if (isGoShelf) {
                            mView.onSuccess(MessageCreator.createMessage(info, GO_REPLENISH_SHELF));
                        } else {
                            loadReplenishCommodity(taskEntity.getBillID());
                        }
                    }

                    @Override
                    public void onError(String msg) {
                        mView.error(msg);
                    }
                });
    }

    @Override
    public void finishReplenishDown(TaskEntity taskEntity,
                                    ReplenishCommodityEntity commodityEntity) {
        Params params = Params.newInstance(Params.Type.MEMBER);
        params.put("billID", taskEntity.getBillID());
        params.put("commodityID", commodityEntity.getCommodityId());
        params.put("stockType", commodityEntity.getStockType());

        FineExApplication.component().http()
                .finishReplenishDown(params)
                .map(new ResponseWrapper<>())
                .compose(mView.toLifecycle())
                .compose(RxUtils.threadSwitch())
                .subscribe(new LoadingObserver<ReplenishStateBean>(mView.provideContext()) {
                    @Override
                    public void onSuccess(ReplenishStateBean info) {
                        mView.success("商品下架完结成功!");
                        if (info.isUpStatus()) {
                            mView.onSuccess(MessageCreator.createMessage(info, REPLENISH_UP_FINISH));
                            return;
                        }
                        if (info.isDownStatus()) {
                            mView.onSuccess(MessageCreator.createMessage(info, REPLENISH_DOWN_FINISH));
                            return;
                        }

                        loadReplenishCommodity(taskEntity.getBillID(), false);
                        loadReplenishCommodity(taskEntity.getBillID());
                    }

                    @Override
                    public void onError(String msg) {
                        mView.error(msg);
                    }
                });
    }
}
